package hsb.ruoyi.framework.web.exception;

import hsb.ruoyi.common.core.domain.AjaxResult;
import hsb.ruoyi.common.exception.DemoModeException;
import hsb.ruoyi.common.exception.ServiceException;
import hsb.ruoyi.common.utils.StringUtils;
import io.vertx.core.http.HttpServerRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.inject.spi.CDI;
import javax.ws.rs.NotSupportedException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

/**
 * 全局异常处理器
 *
 * @author ruoyi
 */
@Provider
public class GlobalExceptionHandler implements ExceptionMapper<Exception> {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);


    @Override
    public Response toResponse(Exception exception) {
        AjaxResult ajaxResult = null;


        if (exception instanceof ServiceException) {
            ajaxResult = handleServiceException((ServiceException) exception, CDI.current().select(HttpServerRequest.class).get());
        }  else if (exception instanceof NotSupportedException) {
            ajaxResult = handleHttpRequestMethodNotSupported((NotSupportedException) exception, CDI.current().select(HttpServerRequest.class).get());
        } else if (exception instanceof RuntimeException) {
            ajaxResult = handleRuntimeException((RuntimeException) exception, CDI.current().select(HttpServerRequest.class).get());
        } else if (exception != null) {
            ajaxResult = handleException(exception, CDI.current().select(HttpServerRequest.class).get());
        }

        return Response.status(200)
                .header("content-type", "application/json")
                .entity(ajaxResult).build();
    }

    /**
     * 权限校验异常
     */
//    public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) {
//        String requestURI = request.getRequestURI();
//        log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
//        return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限，请联系管理员授权");
//    }

    /**
     * 请求方式不支持
     */

    public AjaxResult handleHttpRequestMethodNotSupported(NotSupportedException e,
                                                          HttpServerRequest request) {
        String header = request.getHeader("Content-Type");
        String requestURI = request.path();
        log.error("请求地址'{}',不支持content-type:'{}'", requestURI, header);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 业务异常
     */

    public AjaxResult handleServiceException(ServiceException e, HttpServerRequest request) {
        log.error(e.getMessage(), e);
        Integer code = e.getCode();
        return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
    }

    /**
     * 拦截未知的运行时异常
     */
    public AjaxResult handleRuntimeException(RuntimeException e, HttpServerRequest request) {
        String requestURI = request.path();
        log.error("请求地址'{}',发生未知异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 系统异常
     */
    public AjaxResult handleException(Exception e, HttpServerRequest request) {
        String requestURI = request.path();
        log.error("请求地址'{}',发生系统异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 自定义验证异常
     */
//    public AjaxResult handleBindException(BindException e) {
//        log.error(e.getMessage(), e);
//
//        String message = e.getAllErrors().get(0).getDefaultMessage();
//        return AjaxResult.error(message);
//    }

    /**
     * 自定义验证异常
     */
//    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
//        log.error(e.getMessage(), e);
//        String message = e.getBindingResult().getFieldError().getDefaultMessage();
//        return AjaxResult.error(message);
//    }

    /**
     * 演示模式异常
     */
    public AjaxResult handleDemoModeException(DemoModeException e) {
        return AjaxResult.error("演示模式，不允许操作");
    }


}
